﻿using System.Collections.Generic;
using System.Linq;
using DL.Tools;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.Pool;

namespace DL.AudioSystem
{
    public class AudioManager : Singleton<AudioManager>
    {
        [SerializeField] private AudioMap m_AudioMapSO;
        private IObjectPool<AudioEmitter> m_AudioEmitterPool;
        private List<AudioEmitter> m_ActiveAudioEmitters;
        private Dictionary<SoundType,Queue<AudioEmitter>> m_FrequentAudioEmitters;

        private AudioBuilder m_AudioBuilder;
        
        public AudioEmitter AudioEmitterPrefab;
        public bool CollectionCheck = true;
        public int DefaultCapacity = 20;
        public int MaxPoolSize = 100;
        public int MaxAudioInstances = 40;

        protected override void Construct()
        {
            if (m_AudioMapSO == null)
            {
                Debugger.EO_LogWarning("音频组件资源未添加，初始化失败！");
                return;
            }
            m_AudioMapSO.Init();
            
            m_ActiveAudioEmitters = new();
            m_FrequentAudioEmitters = new();
            m_AudioBuilder = new(this);
            
            foreach (var type in m_AudioMapSO.SoundDataMap)
            {
                foreach (var data in type.Value)
                {
                    if (data.frequentAudio)
                    {
                        m_FrequentAudioEmitters.TryAdd(type.Key, new());
                        break;
                    }
                }
            }
            
            m_AudioEmitterPool = new UnityEngine.Pool.ObjectPool<AudioEmitter>(
                CreateAudioEmitter, 
                OnTakeFromPool, 
                OnReturnedPool,
                OnDestroyPoolObject,
                CollectionCheck, DefaultCapacity, MaxPoolSize
            );
        }

        protected override void Release()
        {
            m_ActiveAudioEmitters.Clear();
            m_FrequentAudioEmitters.Clear();
            m_AudioEmitterPool.Clear();
        }

        /// <summary>
        /// 音频混响器
        /// </summary>
        [SerializeField,Header("音频混响器")]
        private AudioMixer audioMixer;

        /// <summary>
        /// 设置背景音乐声音
        /// </summary>
        /// <param name="value"></param>
        public void SetBGMVolume(float value)
        {
            audioMixer.SetFloat("BGM", value);
        }

        /// <summary>
        /// 设置音效声音
        /// </summary>
        /// <param name="value"></param>
        public void SetSFXVolume(float value)
        {
            audioMixer.SetFloat("SFX", value);
        }
        
        
        public AudioBuilder CreateAudio()
        {
            m_AudioBuilder.Reset();
            return m_AudioBuilder;
        }

        public SoundData GetSoundDataByType(SoundType type,string clipName)
        {
            return GetSoundData(type,clipName);
        }

        public void EqueueFrequentAudioEmitter(SoundType type,AudioEmitter audioEmitter)
        {
            if (m_FrequentAudioEmitters.TryGetValue(type,out var queue))
            {
                queue.Enqueue(audioEmitter);
            }
        }
        
        public bool CanPlayeAudio(SoundType type,SoundData data)
        {
            if (!data.frequentAudio) return true;

            //如果经常播放的音效超出限制
            if (m_FrequentAudioEmitters.Count > MaxAudioInstances &&
                m_FrequentAudioEmitters[type].TryDequeue(out var emitter))
            {
                try
                {
                    emitter.Stop();
                    return true;
                }
                catch
                {
                  Debug.Log("AudioEmitter is already released!");
                }
                return false;
            }
            return true;
        }

        public AudioEmitter Get() => m_AudioEmitterPool.Get();
        public void ReturnToolPool(AudioEmitter audioEmitter) => m_AudioEmitterPool.Release(audioEmitter);

        private AudioEmitter CreateAudioEmitter()
        {
            var item = Instantiate(AudioEmitterPrefab);
            item.gameObject.SetActive(false);
            return item;
        }
        
        private void OnTakeFromPool(AudioEmitter audioEmitter)
        {
            audioEmitter.gameObject.SetActive(true);
            m_ActiveAudioEmitters.Add(audioEmitter);
        }
        
        private void OnReturnedPool(AudioEmitter audioEmitter)
        {
            audioEmitter.gameObject.SetActive(false);
            m_ActiveAudioEmitters.Remove(audioEmitter);
        }
        
        private void OnDestroyPoolObject(AudioEmitter audioEmitter)
        {
            Destroy(audioEmitter);
        }

        //获取方法
        private SoundData GetSoundData(SoundType type, string clipName)
        {
            if (m_AudioMapSO.SoundDataMap.TryGetValue(type, out var list))
            {
                if (string.IsNullOrEmpty(clipName))
                {
                    return list[0];
                }
                var data = list.FirstOrDefault(x => x.name == clipName);
                if (data == null)
                {
                    Debugger.EO_LogWarning(type.ToString() + "对应名称音效未找到！" + clipName);
                }
                return  data ? data : list[0];
            }
            Debugger.EO_LogWarning("未配置对应类型音效！" + type.ToString());
            return null;
        }
    }
}